﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Pkcs;

using Newtonsoft.Json;
using HisGL.CA.NetCA;

namespace HisGL.CA.NetCA
{
  public class NetCAApi : IDisposable
  {
    private string Host { get; set; }

    private string CerFile { get; set; }

    private string CerPassword { get; set; }

    public NetCAApi(string baseUrl)
    {
      this.Host = baseUrl;
      this.CerFile = "";
      this.CerPassword = "";
    }

    public NetCAApi(string baseUrl, string cerFile,string cerPassword)
    {
      this.Host = baseUrl;
      this.CerFile = cerFile;
      this.CerPassword = cerPassword;
    }



    /// <summary>
    /// 2.1.1用户证书查询
    /// </summary>
    /// <param name="userUid">userUid	String	云密钥用户唯一标识</param>
    /// <returns></returns>
    public ResNetCA.QueryCertResponse CertSearch(string userUid)
    {
        return PostJson<ResNetCA.QueryCertResponse>(
                        Host + "/cloudkeyserver/cert/search",
                        new
                        {
                            userUid = userUid,
                        });

    }


    /// <summary>
    /// 2.1.2身份预认证,loginUsage = 0,userLoginType = 1
    /// </summary>
    /// <param name="LoginUsage">0为正常身份认证 1为绑定用户时的身份认证</param>
    /// <param name="UserLoginType">userLoginType	Int	1为口令认证 2为口令+短信认证</param>
    /// <param name="UserPin">userPin	String	对用户输入的口令做Base64编码的值，不能为空</param>
    /// <param name="Cert">cert	Cert	参考Cert结构, 不能为空，该参数通过证书指定了具体的证书用户，参考用户证书查询的响应，</param>
    /// <param name="ApplicationId">applicationId	String	应用id，由云密钥分配，若userLoginType为2，则在2.3 身份预验证之短信验证码校验传applicationId</param>
    /// <returns></returns>
    public ResNetCA.LoginResponse UserCertContentDoLogin(string userPin,ReqNetCA.Cert cert,string applicationId )
    {
        return PostJson<ResNetCA.LoginResponse>(
                        Host + "/cloudkeyserver/user/certcontent/dologin",
                        new
                        {
                          loginUsage = 0,//0为正常身份认证 1为绑定用户时的身份认证
                          userLoginType = 1, //userLoginType	Int	1为口令认证 2为口令+短信认证
                            userPin = Convert.ToBase64String(Encoding.Default.GetBytes(userPin)),
                            cert = new
                            {
                                certContent = cert
                            },
                            applicationId = applicationId
                        });

    }

    /// <summary>
    /// loginUsage = 0,userLoginType = 2
    /// </summary>
    /// <param name="userPin"></param>
    /// <param name="cert"></param>
    /// <param name="applicationId"></param>
    /// <returns></returns>
    public ResNetCA.SmsResponse UserCertContentDoLoginSms(string userPin, ReqNetCA.Cert cert, string applicationId)
    {
      return PostJson<ResNetCA.SmsResponse>(
                      Host + "/cloudkeyserver/user/certcontent/dologin",
                      new
                      {
                        loginUsage = 0,//0为正常身份认证 1为绑定用户时的身份认证
                        userLoginType = 2, //userLoginType	Int	1为口令认证 2为口令+短信认证
                        userPin = Convert.ToBase64String(Encoding.Default.GetBytes(userPin)),
                        cert = new
                        {
                          certContent = cert
                        },
                        applicationId = applicationId
                      });

    }

    /// <summary>
    /// 2.1.4.1接口一：不限定扫码者
    /// </summary>
    /// <param name="loginTypeBitValue">loginTypeBitValue	Int	期望的使用的认证类型参考身份验证类型常量，十进制整形数字，
    /// 通常是高位认证的或运算（8+16+32），可从获取证书所支持的身份验证类型响应获得，可选，不传时默认为服务端支持的全部类型
    /// </param>
    /// <param name="type">认证二维码的类型
    /// 0表示产生以下全部类型的二维码
    /// 3表示产生app无状态的二维码
    /// 4表示产生微信小程序无状态的二维码
    /// </param>
    /// <param name="cert"></param>
    /// <returns></returns>
    public ResNetCA.GenerateNoStatusQrCodeResponse LoginQRCodeNoStatus2CKV1(int loginTypeBitValue,ReqNetCA.Cert cert)
    {
        return PostJson<ResNetCA.GenerateNoStatusQrCodeResponse>(
                        Host + "/cloudkeyserver/api/login/qrcode/nostatus/2CKV1",
                        new
                        {
                          loginTypeBitValue = loginTypeBitValue, 
                          type = 3,
                          cert = new
                          {
                              certContent = cert
                          }
                        });

    }

    /// <summary>
    /// 2.1.4.2接口二：指定扫码者
    /// </summary>
    /// <param name="loginTypeBitValue">loginTypeBitValue	Int	期望的使用的认证类型参考身份验证类型常量，十进制整形数字，
    /// 通常是高位认证的或运算（8+16+32），可从获取证书所支持的身份验证类型响应获得，可选，不传时默认为服务端支持的全部类型
    /// </param>
    /// <param name="cert">参考Cert结构,该参数通过证书指定了具体的证书用户，参考用户证书查询的响应</param>
    /// <returns></returns>
    public ResNetCA.GenerateQrCodeResponse LoginQRCode(int loginTypeBitValue,ReqNetCA.Cert cert)
    {
        return PostJson<ResNetCA.GenerateQrCodeResponse>(
                        Host + "/cloudkeyserver/api/certcontent/login/qrcode",
                        new
                        {
                          loginTypeBitValue = loginTypeBitValue, 
                          cert = new
                          {
                              certContent = cert
                          }
                        });

    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="qrCodeIdentity"></param>
    /// <returns></returns>
    public ResNetCA.QueryQrCodeStatusResponse QRCodeStatus(string qrCodeIdentity)
    {
      return PostJson<ResNetCA.QueryQrCodeStatusResponse>(
                      Host + "/cloudkeyserver/api/qrcode/status",
                      new
                      {
                        qrCodeIdentity = qrCodeIdentity
                      });

    }

    /// <summary>
    /// 9.13.	根据登录令牌查询操作者信息
    /// </summary>
    /// <param name="qrCodeIdentity"></param>
    /// <returns></returns>
    public ResNetCA.OprInfoResponse OprinfoSearch(string userToken)
    {
      return PostJson<ResNetCA.OprInfoResponse>(
                      Host + "/cloudkeyserver/api/oprinfo/search/all",                     
                      new
                      {
                        userToken = userToken
                      });

    }

    /// <summary>
    /// 9.7.电子P7签名
    /// </summary>
    /// <param name="originData"></param>
    /// <param name="detached"></param>
    /// <param name="useSubjectKeyId"></param>
    /// <param name="includeCertOption"></param>
    /// <param name="useQ7"></param>
    /// <param name="useTimestamp"></param>
    /// <param name="userToken"></param>
    /// <returns></returns>
    public ResNetCA.SignResponse PkiSignData(string originData, bool detached, bool useSubjectKeyId, int includeCertOption,
                        bool useQ7, bool useTimestamp, string userToken)
    {
      return PostJson<ResNetCA.SignResponse>(
                      Host + "/cloudkeyserver/pki/signdata",
                      new
                      {
                        originData = originData,
                        detached = detached,
                        useSubjectKeyId = useSubjectKeyId,
                        includeCertOption = includeCertOption,
                        useQ7 = useQ7,
                        useTimestamp = useTimestamp,
                        userToken = userToken
                      });

    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="originData"></param>
    /// <param name="detached"></param>
    /// <param name="signedData"></param>
    /// <param name="verifyTimestamp"></param>
    /// <param name="includeCert"></param>
    /// <param name="cert"></param>
    /// <returns></returns>
    public ResNetCA.BasicResponse PkiVerifySignData(string originData, bool detached, string signedData, bool verifyTimestamp,
                        bool includeCert, ReqNetCA.Cert cert)
    {
      return PostJson<ResNetCA.BasicResponse>(
                      Host + "/cloudkeyserver/pki/verifysigndata",
                      new
                      {
                        originData = originData,
                        detached = detached,
                        signedData = signedData,
                        verifyTimestamp = verifyTimestamp,
                        includeCert = includeCert,
                        certContent = cert
                      });

    }

    /// <summary>
    /// 10.1.下载签章图片
    /// 身份认证通过之后即可调用。（支持证书用户，和被授权人）
    /// </summary>
    /// <param name="userToken"></param>
    /// <returns></returns>
    public ResNetCA.DownloadSealResponse SealDownloadSealPic(string userToken)
    {
      return PostJson<ResNetCA.DownloadSealResponse>(
                      Host + "/cloudkeyserver/seal/downloadsealpic",
                      new
                      {
                        userToken = userToken
                      });

    }

    /// <summary>
    /// 10.4.下载指定格式签章图片
    /// 身份认证通过之后即可调用。（支持证书用户，和被授权人）
    /// </summary>
    /// <param name="userToken"></param>
    /// <param name="format">0：原样输出1：jpg2：bmp3：png</param>
    /// <returns></returns>
    public ResNetCA.DownloadSealResponse SealDownloadSealPic(string userToken, int format)
    {
      return PostJson<ResNetCA.DownloadSealResponse>(
                      Host + "/cloudkeyserver/seal/downloadsealpic/1CKV11",
                      new
                      {
                        userToken = userToken,
                        format = format
                      });

    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="cert"></param>
    /// <returns></returns>
    public ResNetCA.LoginResponse AuthorizedUserCertcontentListAuthorized(ReqNetCA.Cert cert)
    {
      return PostJson<ResNetCA.LoginResponse>(
                      Host + "/cloudkeyserver/authorizeduser/certcontent/list/authorized",
                      new
                      {
                        cert = new
                        {
                          certContent = cert
                        }
                      });

    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="loginUsage"></param>
    /// <param name="authorizedUserId"></param>
    /// <param name="userPin"></param>
    /// <param name="cert"></param>
    /// <param name="applicationId"></param>
    /// <returns></returns>
    public ResNetCA.LoginResponse AuthorizedUserCertcontentPinLogin(int loginUsage, string authorizedUserId, string userPin, ReqNetCA.Cert cert, string applicationId)
    {
      return PostJson<ResNetCA.LoginResponse>(
                      Host + "/cloudkeyserver/authorizeduser/certcontent/pin/login",
                      new
                      {
                        loginUsage = loginUsage,
                        authorizedUserId = authorizedUserId,
                        userPin = Convert.ToBase64String(Encoding.Default.GetBytes(userPin)),
                        cert = new
                        {
                          certContent = cert
                        },
                        applicationId = applicationId
                      });

    }

    /// <summary>
    /// 2.1.6证书用户口令重试次数
    /// </summary>
    /// <param name="cert"></param>
    /// <returns></returns>
    public ResNetCA.QueryPasswordRetryCountResponse CertContentGetSurplusNum(ReqNetCA.Cert cert)
    {
      return PostJson<ResNetCA.QueryPasswordRetryCountResponse>(
                      Host + "/cloudkeyserver/cert/certcontent/getSurplusNum",
                      new
                      {
                        cert = new
                        {
                          certContent = cert
                        }
                      });

    }

    /// <summary>
    /// 2.4.3PDF同步签章
    /// </summary>
    /// <param name="pdfData"></param>
    /// <param name="sealSize"></param>
    /// <param name="position"></param>
    /// <param name="fieldName"></param>
    /// <param name="fieldText"></param>
    /// <param name="useFieldText"></param>
    /// <param name="useTimestamp"></param>
    /// <param name="userToken"></param>
    /// <returns></returns>
    public ResNetCA.PDFSignSealResponse SealPdf(string pdfData, ReqNetCA.SealSize sealSize, ReqNetCA.Position position,
      string fieldName, string fieldText, bool useFieldText, bool useTimestamp, string userToken)
    {
      return PostJson<ResNetCA.PDFSignSealResponse>(
                      Host + "/cloudkeyserver/seal/pdfseal",
                      new
                      {
                        pdfData = pdfData,
                        sealSize = new
                        {
                          width = sealSize.Width != null ? sealSize.Width : 100,
                          height = sealSize.Height != null ? sealSize.Height : 100
                        },
                        position = new
                        {
                          x = position.X != null ? position.X : 100,
                          y = position.Y != null ? position.Y : 100,
                          page = position.Page != null ? position.Page : 100
                        },
                        fieldName = fieldName != null ?fieldName : "" ,
                        fieldText = fieldText != null ? fieldText : "",
                        useFieldText = useFieldText != null ? useFieldText : false,
                        useTimestamp = useTimestamp,
                        userToken = userToken 
                      });

    }

    /// <summary>
    /// PDF验证
    /// </summary>
    /// <param name="pdfData">pdf的base64编码</param>
    /// <param name="verifyLevel">PDF验证等级，验证过程根据验证级别由低到高验证
    /// 0：”校验签名(PDF原文完整性)”
    /// 1：”校验签名时间及更低验证等级”
    /// 2：”校验可信证书链及更低验证等级”
    /// 3：”校验签名时OCSP响应及更低验证等级”
    /// e.g当该参数指定为2时，将执行0、1、2的验证。
    /// 其中，可信证书链在服务器端统一配置，默认为NETCA正式运营证书链
    /// 签名时间，默认使用PDF签章时间或者可信时间戳时间</param>
    /// <returns></returns>
    public ResNetCA.VerifyPDFSealResponse VerifySealPdf(string pdfData, int verifyLevel)
    {
      return PostJson<ResNetCA.VerifyPDFSealResponse>(
                      Host + "/cloudkeyserver/seal/verify/1CKV13",
                      new
                      {
                        pdfData = pdfData,
                        verifyLevel = verifyLevel
                      });

    }

    public ResNetCA.OrganizationInfoResponse OrgRegister1CKV11(string authId, ReqNetCA.Organization organization)
    {
      //https://ip:port/cloudkeyserver/system/interface/org/register/1CKV11

      string requestInfoEncode = JsonConvert.SerializeObject(new
      {
        cloudkeyProjectId = "",
        organization = organization

      });
      byte[] dataBytes = Encoding.UTF8.GetBytes(requestInfoEncode);
      requestInfoEncode = Convert.ToBase64String(dataBytes);

      X509Certificate2 pfx = new X509Certificate2(CerFile, CerPassword, X509KeyStorageFlags.Exportable);
      ContentInfo content = new ContentInfo(dataBytes);//设置要签名的数据,带原文
      SignedCms signedCms = new SignedCms(content);
      CmsSigner signer = new CmsSigner(pfx);
      signer.IncludeOption = X509IncludeOption.EndCertOnly; //仅包含签名的证书即可，无需包含整个证书链
      signedCms.ComputeSignature(signer);//创建签名

      string systemSignature = Convert.ToBase64String(signedCms.Encode());

      return PostJson<ResNetCA.OrganizationInfoResponse>(
                      CerFile,
                      CerPassword,
                      Host + "/cloudkeyserver/system/interface/org/register/1CKV11",
                      new
                      {
                        authId = authId,
                        authType = 1,
                        authCode = "",
                        requestInfoEncode = requestInfoEncode,
                        systemSignature = systemSignature
                      });

    }

    /// <summary>
    /// 8.2.用户信息注册
    /// </summary>
    public ResNetCA.CertContentInfoResponse UserRegister1CKV11(string authId, int userType, ReqNetCA.User user)
    {
      //https://ip:port/cloudkeyserver/system/interface/user/register/1CKV11

      string requestInfoEncode = JsonConvert.SerializeObject(new
      {
        cloudkeyProjectId = "",
        userType = userType,
        user = user

      });
      byte[] dataBytes = Encoding.UTF8.GetBytes(requestInfoEncode);
      requestInfoEncode = Convert.ToBase64String(dataBytes);

      X509Certificate2 pfx = new X509Certificate2(CerFile, CerPassword, X509KeyStorageFlags.Exportable);
      ContentInfo content = new ContentInfo(dataBytes);//设置要签名的数据,带原文
      SignedCms signedCms = new SignedCms(content);
      CmsSigner signer = new CmsSigner(pfx);
      signer.IncludeOption = X509IncludeOption.EndCertOnly; //仅包含签名的证书即可，无需包含整个证书链
      signedCms.ComputeSignature(signer);//创建签名

      string systemSignature = Convert.ToBase64String(signedCms.Encode());

      return PostJson<ResNetCA.CertContentInfoResponse>(
                      CerFile,
                      CerPassword,
                      Host + "/cloudkeyserver/system/interface/user/register/1CKV11",
                      new
                      {
                        authId = authId,
                        authType = 1,
                        authCode = "",
                        requestInfoEncode = requestInfoEncode,
                        systemSignature = systemSignature
                      });

    }

    /// <summary>
    /// 8.3.用户解锁
    /// </summary>
    /// <param name="authId"></param>
    /// <param name="userUid"></param>
    /// <param name="name"></param>
    /// <param name="cert"></param>
    /// <returns></returns>
    public ResNetCA.UserUnLockInfoResponse UserUnLock2CKV6(string authId, string userUid, string name, ReqNetCA.Cert cert)
    {
      //https://ip:port/cloudkeyserver/system/interface/user/unlock/2CKV6

      string requestInfoEncode = JsonConvert.SerializeObject(new
      {
        cloudkeyProjectId = "",
        userUid = userUid,
        name = name,
        cert = cert

      });
      byte[] dataBytes = Encoding.UTF8.GetBytes(requestInfoEncode);
      requestInfoEncode = Convert.ToBase64String(dataBytes);

      X509Certificate2 pfx = new X509Certificate2(CerFile, CerPassword, X509KeyStorageFlags.Exportable);
      ContentInfo content = new ContentInfo(dataBytes);//设置要签名的数据,带原文
      SignedCms signedCms = new SignedCms(content);
      CmsSigner signer = new CmsSigner(pfx);
      signer.IncludeOption = X509IncludeOption.EndCertOnly; //仅包含签名的证书即可，无需包含整个证书链
      signedCms.ComputeSignature(signer);//创建签名

      string systemSignature = Convert.ToBase64String(signedCms.Encode());

      return PostJson<ResNetCA.UserUnLockInfoResponse>(
                      CerFile,
                      CerPassword,
                      Host + "/cloudkeyserver/system/interface/user/unlock/2CKV6",
                      new
                      {
                        authId = authId,
                        authType = 1,
                        authCode = "",
                        requestInfoEncode = requestInfoEncode,
                        systemSignature = systemSignature
                      });

    }

    /// <summary>
    /// 8.5.证书续期
    /// </summary>
    /// <param name="authId"></param>
    /// <param name="cert"></param>
    /// <returns></returns>
    public ResNetCA.CertContentInfoResponse UserCertContentRenewal2CKV8(string authId, ReqNetCA.Cert cert)
    {
      //https://ip:port/cloudkeyserver/system/interface/user/certcontent/renewal/2CKV8

      string requestInfoEncode = JsonConvert.SerializeObject(new
      {
        cert = cert

      });
      byte[] dataBytes = Encoding.UTF8.GetBytes(requestInfoEncode);
      requestInfoEncode = Convert.ToBase64String(dataBytes);

      X509Certificate2 pfx = new X509Certificate2(CerFile, CerPassword, X509KeyStorageFlags.Exportable);
      ContentInfo content = new ContentInfo(dataBytes);//设置要签名的数据,带原文
      SignedCms signedCms = new SignedCms(content);
      CmsSigner signer = new CmsSigner(pfx);
      signer.IncludeOption = X509IncludeOption.EndCertOnly; //仅包含签名的证书即可，无需包含整个证书链
      signedCms.ComputeSignature(signer);//创建签名

      string systemSignature = Convert.ToBase64String(signedCms.Encode());

      return PostJson<ResNetCA.CertContentInfoResponse>(
                      CerFile,
                      CerPassword,
                      Host + "/cloudkeyserver/system/interface/user/certcontent/renewal/2CKV8",
                      new
                      {
                        authId = authId,
                        authType = 1,
                        authCode = "",
                        requestInfoEncode = requestInfoEncode,
                        systemSignature = systemSignature
                      });

    }

    /// <summary>
    /// 8.7.证书注销
    /// </summary>
    /// <param name="authId"></param>
    /// <param name="userType"></param>
    /// <param name="cert"></param>
    /// <returns></returns>
    public ResNetCA.CertContentRevokeResponse UserCertContentRevoke2CKV11(string authId, ReqNetCA.Cert cert)
    {
      //https://ip:port/cloudkeyserver/system/interface/user/certcontent/revoke/2CKV11

      string requestInfoEncode = JsonConvert.SerializeObject(new
      {
        cert = cert

      });
      byte[] dataBytes = Encoding.UTF8.GetBytes(requestInfoEncode);
      requestInfoEncode = Convert.ToBase64String(dataBytes);

      X509Certificate2 pfx = new X509Certificate2(CerFile, CerPassword, X509KeyStorageFlags.Exportable);
      ContentInfo content = new ContentInfo(dataBytes);//设置要签名的数据,带原文
      SignedCms signedCms = new SignedCms(content);
      CmsSigner signer = new CmsSigner(pfx);
      signer.IncludeOption = X509IncludeOption.EndCertOnly; //仅包含签名的证书即可，无需包含整个证书链
      signedCms.ComputeSignature(signer);//创建签名

      string systemSignature = Convert.ToBase64String(signedCms.Encode());

      return PostJson<ResNetCA.CertContentRevokeResponse>(
                      CerFile,
                      CerPassword,
                      Host + "/cloudkeyserver/system/interface/user/certcontent/revoke/2CKV11",
                      new
                      {
                        authId = authId,
                        authType = 1,
                        authCode = "",
                        requestInfoEncode = requestInfoEncode,
                        systemSignature = systemSignature
                      });

    }

    /// <summary>
    /// 9.22.证书状态查询
    /// </summary>
    /// <param name="cert"></param>
    /// <returns></returns>
    public ResNetCA.CertContentStatusInfoResponse UserCertContentStatus2CKV15(ReqNetCA.Cert cert)
    {
      return PostJson<ResNetCA.CertContentStatusInfoResponse>(
                      Host + "/cloudkeyserver/cert/certcontent/status/2CKV15",
                      new
                      {
                        cert = new
                        {
                          certContent = cert
                        }
                      });

    }

    public ResNetCA.CertContentParseInfoResponse UserCertContentParse1CKV13(ReqNetCA.Cert cert)
    {
        return PostJson<ResNetCA.CertContentParseInfoResponse>(
                        Host + "/cloudkeyserver/cert/certcontent/parse/1CKV13",
                        new
                        {
                            cert = new
                            {
                                certContent = cert
                            }
                        });

    }


    /// <summary>
    /// 发送JSON请求
    /// </summary>
    /// <param name="url">请求地址</param>
    /// <param name="json">请求JSON</param>
    /// <param name="timeout">超时时间（秒）</param>
    /// <returns>响应对象</returns>
    private T PostJson<T>(string url, object json, int timeout = 10)
    {
      try
      {
        var jsonString = JsonConvert.SerializeObject(json);
        var jsonBytes = Encoding.UTF8.GetBytes(jsonString);
        HttpWebRequest request = HttpWebRequest.Create(url) as HttpWebRequest;
        request.Method = "POST";
        request.ContentType = "application/json;charset=UTF-8";
        request.ContentLength = jsonBytes.Length;
        request.Timeout = timeout * 1000;
        ServicePointManager.ServerCertificateValidationCallback = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => { return true; };
        using (var writer = request.GetRequestStream())
        {
          writer.Write(jsonBytes, 0, jsonBytes.Length);

          HttpWebResponse response = request.GetResponse() as HttpWebResponse;
          using (StreamReader reader = new StreamReader(response.GetResponseStream()))
          {
            return JsonConvert.DeserializeObject<T>(reader.ReadToEnd());
          }
        }
      }
      catch (Exception ex)
      {
        throw new Exception(string.Format("请求失败：{0}", ex.Message));
      }
    }

    private T PostJson<T>(string cerFile, string password, string url, object json, int timeout = 10)
    {
      try
      {
        var jsonString = JsonConvert.SerializeObject(json);
        var jsonBytes = Encoding.UTF8.GetBytes(jsonString);
        HttpWebRequest request = HttpWebRequest.Create(url) as HttpWebRequest;
        request.Method = "POST";
        request.ContentType = "application/json;charset=UTF-8";
        request.ContentLength = jsonBytes.Length;
        request.Timeout = timeout * 1000;
        X509Certificate cer = new X509Certificate2(cerFile, password);
        request.ClientCertificates.Add(cer); 

        ServicePointManager.ServerCertificateValidationCallback = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => { return true; };
        using (var writer = request.GetRequestStream())
        {
          writer.Write(jsonBytes, 0, jsonBytes.Length);

          HttpWebResponse response = request.GetResponse() as HttpWebResponse;
          using (StreamReader reader = new StreamReader(response.GetResponseStream()))
          {
            return JsonConvert.DeserializeObject<T>(reader.ReadToEnd());
          }
        }
      }
      catch (Exception ex)
      {
        throw new Exception(string.Format("请求失败：{0}", ex.Message));
      }
    }

    /// <summary>
    /// 释放
    /// </summary>
    public void Dispose()
    {

    } 
  }
}
